package br.dcc.ufmg.persistence;

import java.sql.ResultSet;
import java.sql.Statement;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import br.dcc.ufmg.domain.Measure;

public abstract class ArtifactDAO<T extends Measure> {

    public abstract String buildSqlArtifactsMeasures(String project, T artifact,
            String metric);

    public void addMeasuresArtifacts(List<T> artifacts, String sources,
            String metric) throws Exception {
        for (T artifact : artifacts) {
        	System.out.println("getting");
            String sql = buildSqlArtifactsMeasures(sources, artifact, metric);
            Statement stmt = HSQLDBConnection.getConnection().createStatement();
        	System.out.println(sql);
            ResultSet rs = stmt.executeQuery(sql);
            Map<String, Float> measures;
            if (artifact.getMeasures() != null) {
                measures = artifact.getMeasures();
            } else {
                measures = new LinkedHashMap<>();
            }
            while (rs.next()) {
                measures.put(rs.getString("metric_id"), rs.getFloat("value"));
            }
            stmt.close();
            artifact.setMeasures(measures);
        }
        System.out.println(artifacts.size());
    }

    private List<String> getSources(String system) throws Exception {
        String sql = "SELECT scope FROM source WHERE system = '"
                + system + "'";
        Statement stmt = HSQLDBConnection.getConnection().createStatement();
        ResultSet rs = stmt.executeQuery(sql);
        List<String> sources = new LinkedList<>();
        while (rs.next()) {
            sources.add(rs.getString(1));
        }
        return sources;
    }
    
    private String getSourcesInSql(String system) throws Exception {
        List<String> sources = getSources(system);
        StringBuilder sb = new StringBuilder("(");
        for (String source : sources) {
            sb.append(" source_id = '").append(source).append("' OR ");
        }
        String sqlSources = sb.substring(0, sb.length() - 4);
        sqlSources += ")";
        return sqlSources;
    } 
    

    public List<T> getArtifacts(String system) throws Exception {
        String sources = getSourcesInSql(system);
        String sql = "SELECT metric_id FROM measurement WHERE "
                + " per = '" + getStringType() + "'";
        Statement stmt = HSQLDBConnection.getConnection().createStatement();
        ResultSet rs = stmt.executeQuery(sql);
        List<T> artifacts = null;
        while (rs.next()) {
        	System.out.println("next method");
            String metric = rs.getString(1);
            if (artifacts == null) {
            	System.out.println("next artifacsByMetric");
            	artifacts = getArtifactsByMetric(sources, metric);
            	System.out.println("end artifacsByMetric");

            }
        	System.out.println("next addMeasures");
            addMeasuresArtifacts(artifacts, sources, metric);
        	System.out.println("end addMeasures");

        }
        return artifacts;
    }

    protected abstract String getStringType();

    protected abstract T createArtifactFromResultSet(ResultSet rs) throws Exception;

    private List<T> getArtifactsByMetric(String sources, String metric)
            throws Exception {
        List<T> artifacts = new LinkedList<T>();
        String sql = "SELECT name as name, source as source, package as package FROM measure WHERE "
                + " metric_id = '" + metric + "'";
        Statement stmt = HSQLDBConnection.getConnection().createStatement();
        ResultSet rs = stmt.executeQuery(sql);
        while (rs.next()) {
            T artifact = createArtifactFromResultSet(rs);
            artifacts.add(artifact);
        }
        stmt.close();
        return artifacts;
    }

}
